{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "### 朴素贝叶斯\n",
    "\n",
    "朴素贝叶斯（Naive Bayes）是一种基于贝叶斯定理的简单概率分类算法，属于生成模型。它假设特征之间相互独立，即“朴素”意味着特征条件独立性假设。尽管这一假设在现实中往往不成立，但朴素贝叶斯在许多实际应用中表现良好，尤其是在文本分类、垃圾邮件过滤、情感分析等领域。"
   ],
   "id": "d41d0069f827c066"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.132153Z",
     "start_time": "2025-01-12T11:00:43.125738Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from sklearn.datasets import fetch_20newsgroups\n",
    "import numpy as np\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.feature_extraction.text import TfidfVectorizer\n",
    "import time\n",
    "from sklearn.naive_bayes import MultinomialNB\n",
    "from sklearn.metrics import classification_report\n",
    "from sklearn.metrics import roc_auc_score"
   ],
   "id": "37fe3e7fb16cad33",
   "outputs": [],
   "execution_count": 127
  },
  {
   "cell_type": "code",
   "id": "f5b6e51840be5d36",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.404175Z",
     "start_time": "2025-01-12T11:00:43.188562Z"
    }
   },
   "source": [
    "# 读取数据\n",
    "news = fetch_20newsgroups(subset='all', data_home='C:/Users/DELL/scikit_learn_data')"
   ],
   "outputs": [],
   "execution_count": 128
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.408784Z",
     "start_time": "2025-01-12T11:00:43.404175Z"
    }
   },
   "cell_type": "code",
   "source": "print(len(news.data))  # 样本数，包含的特征",
   "id": "a0f605128642d579",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "18846\n"
     ]
    }
   ],
   "execution_count": 129
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.413794Z",
     "start_time": "2025-01-12T11:00:43.408784Z"
    }
   },
   "cell_type": "code",
   "source": "print(news.data[0]) # 第一个样本 特征",
   "id": "c2a90b5e6ea9eec7",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "From: Mamatha Devineni Ratnam <mr47+@andrew.cmu.edu>\n",
      "Subject: Pens fans reactions\n",
      "Organization: Post Office, Carnegie Mellon, Pittsburgh, PA\n",
      "Lines: 12\n",
      "NNTP-Posting-Host: po4.andrew.cmu.edu\n",
      "\n",
      "\n",
      "\n",
      "I am sure some bashers of Pens fans are pretty confused about the lack\n",
      "of any kind of posts about the recent Pens massacre of the Devils. Actually,\n",
      "I am  bit puzzled too and a bit relieved. However, I am going to put an end\n",
      "to non-PIttsburghers' relief with a bit of praise for the Pens. Man, they\n",
      "are killing those Devils worse than I thought. Jagr just showed you why\n",
      "he is much better than his regular season stats. He is also a lot\n",
      "fo fun to watch in the playoffs. Bowman should let JAgr have a lot of\n",
      "fun in the next couple of games since the Pens are going to beat the pulp out of Jersey anyway. I was very disappointed not to see the Islanders lose the final\n",
      "regular season game.          PENS RULE!!!\n",
      "\n",
      "\n"
     ]
    }
   ],
   "execution_count": 130
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.418718Z",
     "start_time": "2025-01-12T11:00:43.414799Z"
    }
   },
   "cell_type": "code",
   "source": "print(news.target) #标签",
   "id": "8e86421235a60d3f",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10  3 17 ...  3  1  7]\n"
     ]
    }
   ],
   "execution_count": 131
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.423973Z",
     "start_time": "2025-01-12T11:00:43.418718Z"
    }
   },
   "cell_type": "code",
   "source": [
    "print(np.unique(news.target)) #标签的类别,共20类\n",
    "print(len(np.unique(news.target)))"
   ],
   "id": "4b0a646924e2c2e0",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]\n",
      "20\n"
     ]
    }
   ],
   "execution_count": 132
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.428119Z",
     "start_time": "2025-01-12T11:00:43.423973Z"
    }
   },
   "cell_type": "code",
   "source": "print(news.target_names) #标签的名字",
   "id": "initial_id",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['alt.atheism', 'comp.graphics', 'comp.os.ms-windows.misc', 'comp.sys.ibm.pc.hardware', 'comp.sys.mac.hardware', 'comp.windows.x', 'misc.forsale', 'rec.autos', 'rec.motorcycles', 'rec.sport.baseball', 'rec.sport.hockey', 'sci.crypt', 'sci.electronics', 'sci.med', 'sci.space', 'soc.religion.christian', 'talk.politics.guns', 'talk.politics.mideast', 'talk.politics.misc', 'talk.religion.misc']\n"
     ]
    }
   ],
   "execution_count": 133
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.443286Z",
     "start_time": "2025-01-12T11:00:43.428119Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 进行数据分割\n",
    "x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25, random_state=1)"
   ],
   "id": "a287261352cac47f",
   "outputs": [],
   "execution_count": 134
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:43.456709Z",
     "start_time": "2025-01-12T11:00:43.443286Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 对数据集进行特征抽取\n",
    "# 将文本数据转换为数值形式的特征矩阵\n",
    "# # 初始化 TfidfVectorizer\n",
    "tf = TfidfVectorizer()"
   ],
   "id": "496c29aded58e5ce",
   "outputs": [],
   "execution_count": 135
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:47.224229Z",
     "start_time": "2025-01-12T11:00:43.456709Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 以训练集当中的词的列表进行每篇文章重要性统计['a','b','c','d']\n",
    "# 返回训练集转换后的 TF-IDF 特征矩阵（稀疏矩阵）\n",
    "x_train = tf.fit_transform(x_train)"
   ],
   "id": "96e82a9828f6a22e",
   "outputs": [],
   "execution_count": 136
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:47.347471Z",
     "start_time": "2025-01-12T11:00:47.224229Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#针对特征内容，下面的打印可以得到特征数目，总计有15万特征\n",
    "print(len(tf.get_feature_names_out()))"
   ],
   "id": "92b391b42f1de7d9",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "153196\n"
     ]
    }
   ],
   "execution_count": 137
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:47.472424Z",
     "start_time": "2025-01-12T11:00:47.347471Z"
    }
   },
   "cell_type": "code",
   "source": "print(tf.get_feature_names_out()[100000])# 获取词汇表特征名称（第100001个）",
   "id": "af5835a0cd55e3a1",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "murky\n"
     ]
    }
   ],
   "execution_count": 138
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:47.595175Z",
     "start_time": "2025-01-12T11:00:47.472424Z"
    }
   },
   "cell_type": "code",
   "source": "print(tf.get_feature_names_out()[0:10])# 获取词汇表特征名称（前10个）",
   "id": "d3ca931ef4080c73",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['00' '000' '0000' '00000' '0000000004' '0000000005' '0000000667'\n",
      " '0000001200' '000003' '000005102000']\n"
     ]
    }
   ],
   "execution_count": 139
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:47.718817Z",
     "start_time": "2025-01-12T11:00:47.595175Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 进行朴素贝叶斯算法的预测,alpha是拉普拉斯平滑系数，分子和分母加上一个系数，分母加alpha*特征词数目\n",
    "mlt = MultinomialNB(alpha=1.0)\n",
    "\n",
    "# print(x_train.toarray())\n",
    "\n",
    "# 训练\n",
    "start=time.time()\n",
    "mlt.fit(x_train, y_train)\n",
    "end=time.time()\n",
    "end-start #统计训练时间"
   ],
   "id": "6508ab789e51bdb9",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.10938405990600586"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 140
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.584141Z",
     "start_time": "2025-01-12T11:00:47.718817Z"
    }
   },
   "cell_type": "code",
   "source": [
    "x_transform_test = tf.transform(x_test)  # 如果遇到训练集中没有的新词，则直接丢弃，确保特征数目保持一致\n",
    "print(len(tf.get_feature_names_out())) # 查看特征数目，特征数目不发生改变"
   ],
   "id": "c692438de5034d73",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "153196\n"
     ]
    }
   ],
   "execution_count": 141
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.612687Z",
     "start_time": "2025-01-12T11:00:48.584141Z"
    }
   },
   "cell_type": "code",
   "source": [
    "start=time.time()\n",
    "# 使用训练好的模型对转换后的测试数据（x_transform_test）进行预测，并返回预测结果（y_predict）\n",
    "y_predict = mlt.predict(x_transform_test)\n",
    "\n",
    "end=time.time()\n",
    "end-start# 统计测试时间"
   ],
   "id": "71733f5db7d3d4c2",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.019670486450195312"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 142
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.642642Z",
     "start_time": "2025-01-12T11:00:48.612687Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 获取测试结果\n",
    "print(\"预测的前面10篇文章类别为：\", y_predict[0:10])\n",
    "# 得出准确率\n",
    "print(\"准确率为：\", mlt.score(x_transform_test, y_test))"
   ],
   "id": "cdf6bdb48d8818e3",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测的前面10篇文章类别为： [16 19 18  1  9 15  1  2 16 13]\n",
      "准确率为： 0.8518675721561969\n"
     ]
    }
   ],
   "execution_count": 143
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "### AUC（Area Under the Curve）指标和ROC（Receiver Operating Characteristic）曲线\n",
    "\n",
    "ROC 曲线通过绘制 真正例率（True Positive Rate, TPR） 和 假正例率（False Positive Rate, FPR） 的关系，直观地反映模型在不同分类阈值下的性能。\n",
    "\n",
    "      横轴（X 轴）：假正例率（False Positive Rate, FPR）\n",
    "      \n",
    "      纵轴（Y 轴）：真正例率（True Positive Rate, TPR）也称为 召回率（Recall）\n",
    "\n",
    "AUC 是 ROC 曲线（Receiver Operating Characteristic Curve）下的面积，取值范围在 0 到 1 之间。AUC 值越接近 1，模型的分类性能越好；AUC 值越接近 0.5，模型的分类性能越差（相当于随机猜测）。"
   ],
   "id": "6fc1defe5cb33384"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.647960Z",
     "start_time": "2025-01-12T11:00:48.642642Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#预测的文章数目\n",
    "len(y_predict)"
   ],
   "id": "c630e50d61935e17",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4712"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 144
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.658773Z",
     "start_time": "2025-01-12T11:00:48.647960Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 目前这个场景我们不需要召回率，support是真实的为那个类别的有多少个样本\n",
    "print(classification_report(y_test, y_predict,\n",
    "      target_names=news.target_names))"
   ],
   "id": "5d9b64e4fa1b9048",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                          precision    recall  f1-score   support\n",
      "\n",
      "             alt.atheism       0.91      0.77      0.83       199\n",
      "           comp.graphics       0.83      0.79      0.81       242\n",
      " comp.os.ms-windows.misc       0.89      0.83      0.86       263\n",
      "comp.sys.ibm.pc.hardware       0.80      0.83      0.81       262\n",
      "   comp.sys.mac.hardware       0.90      0.88      0.89       234\n",
      "          comp.windows.x       0.92      0.85      0.88       230\n",
      "            misc.forsale       0.96      0.67      0.79       257\n",
      "               rec.autos       0.90      0.87      0.88       265\n",
      "         rec.motorcycles       0.90      0.95      0.92       251\n",
      "      rec.sport.baseball       0.89      0.96      0.93       226\n",
      "        rec.sport.hockey       0.95      0.98      0.96       262\n",
      "               sci.crypt       0.76      0.97      0.85       257\n",
      "         sci.electronics       0.84      0.80      0.82       229\n",
      "                 sci.med       0.97      0.86      0.91       249\n",
      "               sci.space       0.92      0.96      0.94       256\n",
      "  soc.religion.christian       0.55      0.98      0.70       243\n",
      "      talk.politics.guns       0.76      0.96      0.85       234\n",
      "   talk.politics.mideast       0.93      0.99      0.96       224\n",
      "      talk.politics.misc       0.98      0.56      0.72       197\n",
      "      talk.religion.misc       0.97      0.26      0.41       132\n",
      "\n",
      "                accuracy                           0.85      4712\n",
      "               macro avg       0.88      0.84      0.84      4712\n",
      "            weighted avg       0.87      0.85      0.85      4712\n",
      "\n"
     ]
    }
   ],
   "execution_count": 145
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.663179Z",
     "start_time": "2025-01-12T11:00:48.658773Z"
    }
   },
   "cell_type": "code",
   "source": "y_test.shape #测试集中有多少样本",
   "id": "b8556695e6f089dd",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(4712,)"
      ]
     },
     "execution_count": 146,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 146
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.667013Z",
     "start_time": "2025-01-12T11:00:48.663179Z"
    }
   },
   "cell_type": "code",
   "source": [
    "y_test1 = np.where(y_test == 0, 1, 0)\n",
    "print(y_test1.sum()) #label为0的样本数"
   ],
   "id": "2fc767a0d047883e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "199\n"
     ]
    }
   ],
   "execution_count": 147
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.670905Z",
     "start_time": "2025-01-12T11:00:48.667013Z"
    }
   },
   "cell_type": "code",
   "source": [
    "y_predict1 = np.where(y_predict == 0, 1, 0)\n",
    "print(y_predict1.sum())"
   ],
   "id": "4c65131727b286d2",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "168\n"
     ]
    }
   ],
   "execution_count": 148
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.675519Z",
     "start_time": "2025-01-12T11:00:48.670905Z"
    }
   },
   "cell_type": "code",
   "source": "(y_test1*y_predict1).sum()# 两矩阵相乘，统计其中1的个数，即为TP值",
   "id": "138b12c6072b39cf",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.int64(153)"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 149
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:48.683024Z",
     "start_time": "2025-01-12T11:00:48.675519Z"
    }
   },
   "cell_type": "code",
   "source": [
    "max(y_test), min(y_test)\n",
    "# 把0-19总计20个分类，变为0和1\n",
    "# 5是可以改为0到19的\n",
    "y_test1 = np.where(y_test == 5, 1, 0)\n",
    "print('label为5的样本数:',y_test1.sum())  #label为5的样本数\n",
    "y_predict1 = np.where(y_predict == 5, 1, 0)\n",
    "print('预测label为5的数量:',y_predict1.sum())\n",
    "# roc_auc_score的y_test只能是二分类,针对多分类如何计算AUC\n",
    "print(\"AUC指标：\", roc_auc_score(y_test1, y_predict1))\n",
    "y_test1, y_predict1"
   ],
   "id": "f137fc578e22cc62",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "label为5的样本数: 230\n",
      "预测label为5的数量: 214\n",
      "AUC指标： 0.924078924393225\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(array([0, 0, 0, ..., 0, 0, 0], shape=(4712,)),\n",
       " array([0, 0, 0, ..., 0, 0, 0], shape=(4712,)))"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 150
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-12T11:00:54.070599Z",
     "start_time": "2025-01-12T11:00:54.050891Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#算多分类的精确率，召回率，F1-score\n",
    "FP = np.where((np.array(y_test1) - np.array(y_predict1)) == -1, 1, 0).sum()\n",
    "print('FP:',FP)\n",
    "TP = y_predict1.sum() - FP\n",
    "print('TP:',TP)\n",
    "FN = np.where((np.array(y_test1) - np.array(y_predict1)) == 1, 1, 0).sum()\n",
    "print('FN:',FN) \n",
    "TN = np.where(y_test1 == 0, 1, 0).sum() - FP\n",
    "print('TN:',TN)\n",
    "print('精确率为',TP / (TP + FP))  #精确率\n",
    "print('召回率为',TP / (TP + FN))  #召回率\n",
    "#F1-score\n",
    "2 * TP / (2 * TP + FP + FN).sum()"
   ],
   "id": "a8b210a95e098e02",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FP: 18\n",
      "TP: 196\n",
      "FN: 34\n",
      "TN: 4464\n",
      "精确率为 0.9158878504672897\n",
      "召回率为 0.8521739130434782\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "np.float64(0.8828828828828829)"
      ]
     },
     "execution_count": 151,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 151
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
